package com.dhms.vostok1.utils

import android.util.Log
import com.dhms.vostok1.service.net.NetworkApi
import org.java_websocket.drafts.Draft_6455
import org.java_websocket.enums.ReadyState
import java.net.URI
import java.util.*
import java.util.concurrent.locks.ReentrantLock

/*网络状态*/
enum class NetworkState {
    UNKNOWN, NETWORK_NO, NETWORK
}

class MessageCenterWebSocket(
    private var receiveMessage: (message: String) -> Unit,
    private var networkChange: (state: NetworkState) -> Unit,
) {
    private var webSocketClient: MessageClient? = null

    private var connectionLostTimeout = 1

    //5s重连一次
    private var reconnectTime = (5 * 1000).toLong()

    private var timer: Timer? = null

    private var networkStateLocker = ReentrantLock()
    private var networkState: NetworkState = NetworkState.UNKNOWN
        set(value) {
            //防止重复发
            try {
                networkStateLocker.lock()

                if (field == NetworkState.UNKNOWN && value == NetworkState.NETWORK) {
                    field = value
                    networkChange(value)
                } else {
                    startTimer(value, fun(b: NetworkState) {
                        if (field != value) {
                            field = value
                            networkChange(b)
                            Log.d(MessageClient.OFFLINE_DEBUG_TAG, "networkChange:${b}")
                        }
                    })
                }
            } finally {
                networkStateLocker.unlock()
            }
        }


    fun createWebSocket() {
        if (NetworkApi.baseUrl == null) {
            Log.i(TAG, "baseUrl:${NetworkApi.baseUrl}")
            Log.d(MessageClient.OFFLINE_DEBUG_TAG, "baseUrl:${NetworkApi.baseUrl}")
        }
        val url = "${NetworkApi.wsUrl}/ws/v1/connect?tkn=${NetworkApi.token}"
        Log.i(TAG, "wsUrl: $url")
        Log.d(MessageClient.OFFLINE_DEBUG_TAG, "wsUrl: $url")
        webSocketClient = MessageClient(
            URI(
                url
            ), Draft_6455()
        ) // more about drafts here: http://github.com/TooTallNate/Java-WebSocket/wiki/Drafts
        webSocketClient?.setListener(object : MessageClient.Listener {
            override fun onMessage(message: String) {
                receiveMessage(message)
            }

            override fun onOpen() {
                networkState = NetworkState.NETWORK
            }

            override fun onError(ex: Exception) {
                /*说明 无网络*/
//                if (ex.cause?.message?.contains(NetWorkUnreachable) == true) {
//                    networkState = NetworkState.NETWORK_NO
//                }
            }

            override fun onClose(code: Int, reason: String) {
                /*说明 无网络*/
                networkState = NetworkState.NETWORK_NO
            }
        })
        webSocketClient?.let {
            it.connectionLostTimeout = connectionLostTimeout
            reconnectSocket()
        }
    }

    private fun startTimer(value: NetworkState, callback: (b: NetworkState) -> Unit) {
        Log.d(MessageClient.OFFLINE_DEBUG_TAG, "1: ${value.name}")
        timer?.cancel()
        timer = Timer()
        timer?.schedule(object : TimerTask() {
            override fun run() {
                Log.d(MessageClient.OFFLINE_DEBUG_TAG, "2: ${value.name}")
                callback(value)
                if (value == NetworkState.NETWORK_NO) {
                    Log.d(MessageClient.OFFLINE_DEBUG_TAG, "3-reconnect: ${value.name}")
                    reconnectSocket()
                } else if (value == NetworkState.NETWORK) {
                    Log.d(MessageClient.OFFLINE_DEBUG_TAG, "3-stop_timer: ${value.name}")
                    stopTimer()
                }
            }
        }, reconnectTime)
    }

    private fun stopTimer() {
        if (timer != null) {
            timer?.cancel()
            timer = null
        }
    }

    //断线重连
    fun reconnectSocket() {
        webSocketClient?.let {
            try {
                when (it.readyState) {
                    ReadyState.NOT_YET_CONNECTED -> {
                        Log.i(
                            TAG,
                            "WebSocketConnectBlocking链接"
                        )
                        it.connectBlocking()
                    }
                    ReadyState.CLOSING, ReadyState.CLOSED -> {
                        Log.i(
                            TAG,
                            "WebSocketReconnectBlocking链接"
                        )
                        it.reconnectBlocking()
                    }
                    else -> {
                        return@let
                    }
                }
            } catch (e: Exception) {
                Log.i(TAG, "reconnectSocket: ${e.fillInStackTrace()}")
            }
        }
    }

    fun closeWebSocket() {
        stopTimer()
        if (webSocketClient != null) {
            webSocketClient?.close()
            webSocketClient = null
        }
    }

    companion object {
        const val TAG = "MessageCenterWebSocket"

        //无网络
        const val NetWorkUnreachable = "Network is unreachable"
    }

}